package com.infinitus.activity.web;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.infinitus.activity.common.RedisKey;
import com.infinitus.activity.common.WebConstant;
import com.infinitus.activity.redis.RedisService;
import com.infinitus.activity.util.HttpClientConnectionManager;

/**
 * @create: 2019/1/9
 * @desc:
 */
@SuppressWarnings("deprecation")
@Controller
@RequestMapping(value = "/wechat")
public class WechatController {
    @Value("${wechat.appId}")
    public String appId;
    @Value("${wechat.appSecret}")
    public String appSecret;
    @Autowired
    RedisService redisService;

    private static Logger logger = LoggerFactory.getLogger(com.infinitus.activity.web.WechatController.class);
    private static final String OPEN_ID_API = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=";
    private static final String USER_INFO_API = "https://api.weixin.qq.com/sns/userinfo?lang=zh_CN&openid=";


    @RequestMapping(value = "/getJSWXconfig")
    @ResponseBody
    public Map<String, Object> getJSWXconfig(String url) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        Map<String, Object> result = new HashMap<String, Object>();
        if (url == null || url.isEmpty()) {
            resultMap.put(WebConstant.RESULT_FILED, WebConstant.FAIL);
            resultMap.put(WebConstant.RESULT_MESSAGE, "url不能为空!");
            return resultMap;
        }
        try {
            String noncestr = RandomStringUtils.randomAlphanumeric(16);
            String jsapi_ticket = redisService.get(RedisKey.WECHAT_jsTicker).toString();
            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
            result.put("appId", appId);
            result.put("timestamp", timestamp);
            result.put("nonceStr", noncestr);
            result.put("signature", signature(noncestr, jsapi_ticket, timestamp, url));
            resultMap.put(WebConstant.RESULT_FILED, WebConstant.SUCCESS);
            resultMap.put(WebConstant.RESULT_DATA, result);
        } catch (Exception e) {
            resultMap.put(WebConstant.RESULT_FILED, WebConstant.FAIL);
            resultMap.put(WebConstant.RESULT_MESSAGE, "请求获取微信分享授权失败!");
        }
        return resultMap;
    }

    /**
     * 微信js签名
     * @param noncestr
     * @param jsapi_ticket
     * @param timestamp
     * @param url
     * @return
     */
    public static String signature(String noncestr, String jsapi_ticket, String timestamp, String url) {
        logger.info("noncestr: " + noncestr);
        logger.info("jsapi_ticket: " + jsapi_ticket);
        logger.info("timestamp: " + timestamp);
        logger.info("url: " + url);
        TreeMap<String, String> params = new TreeMap<String, String>();
        params.put("noncestr", noncestr);
        params.put("jsapi_ticket", jsapi_ticket);
        params.put("timestamp", timestamp);
        params.put("url", url);
        StringBuffer result = new StringBuffer();
        boolean firstParam = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();
            if (!firstParam) {
                result.append("&");
            }
            firstParam = false;
            result.append(name).append("=").append(value);
        }
        logger.info(result.toString());
        String sign = DigestUtils.shaHex(result.toString());
        logger.info("sign: " + sign);
        return sign;
    }
    /**
     *
     * @Title: getWechatInfo
     * @Description: 获取用户相关的信息
     * @author    add   by zhangxh 2017年5月4日 上午10:32:28
     * @param request
     * @return
     * @throws
     *
     */
    @RequestMapping(value = "/getWechatInfo")
    @ResponseBody
    public Object getWechatInfo(HttpServletRequest request) {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        logger.info("code:{}",code);
        logger.info("state:{}",state);
        Map<String, String> openIdMap = getOpenId(request);
        String openId = openIdMap.get("openId");
        if("snsapi_userinfo".equals(state)){//返回相关的用户信息
            String result = getUserInfo(openId, openIdMap.get("accessToken"),openIdMap.get("refreshToken"));
            return result;
        }else{//只返回openId
            return openId;
        }
    }

    /**
     * 获取OpenId
     * @param request
     * @param appId
     * @param appSecret
     * @return
     * @throws Exception
     */
    @SuppressWarnings({ "resource" })
    private  Map<String,String> getOpenId(ServletRequest request){
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        logger.info("code"+ code);
        logger.info("state"+ state);
        DefaultHttpClient httpclient = null;
        Map<String, String> map = new HashMap<String, String>();
        try {
            httpclient = new DefaultHttpClient();
            httpclient = (DefaultHttpClient) HttpClientConnectionManager.getSSLInstance(httpclient);
            String url = OPEN_ID_API + appId + "&secret=" + appSecret + "&code="+code+
                    "&grant_type=authorization_code";
            HttpGet httpost = HttpClientConnectionManager.getGetMethod(url);

            HttpResponse res = httpclient.execute(httpost);
            String jsonStr = EntityUtils.toString(res.getEntity(), "utf-8");
            logger.info(jsonStr);
            ObjectMapper mapper = new ObjectMapper(); //转换器
            Map result = mapper.readValue(jsonStr, Map.class); //json转换成map
//			JsonObject result = new JsonParser().parse(jsonStr).getAsJsonObject();
            String openid = null;
            String accessToken = null;
            String refreshToken = null;
            if(result.containsKey("openid")){
                openid = result.get("openid").toString();
                accessToken = result.get("access_token").toString();
                refreshToken = result.get("refresh_token").toString();
                map.put("openId", openid);
                map.put("accessToken", accessToken);
                map.put("refreshToken", refreshToken);
                logger.info("get openid: "+openid);
                return map;
            }else{
                String err = formatStr("获取openID失败，code值为",code,",state值为",state,",result:",jsonStr);
                logger.error(err);
            }
        } catch(Exception e){
            logger.error("获取openID失败:",e);
        } finally {
            if(httpclient != null)
                httpclient.close();
        }
        return map;
    }

    /**
     * 获取用户基本信息
     * @param request
     * @param appId
     * @param appSecret
     * @return
     * @throws Exception
     */
    private String getUserInfo(String openId,String accessToken,String refreshToken){
        DefaultHttpClient httpclient = null;
        try {
            httpclient = new DefaultHttpClient();
            httpclient = (DefaultHttpClient) HttpClientConnectionManager.getSSLInstance(httpclient);
            String url = USER_INFO_API + openId + "&access_token=" + accessToken;
            HttpGet httpost = HttpClientConnectionManager.getGetMethod(url);
            HttpResponse res = httpclient.execute(httpost);
            String jsonStr = EntityUtils.toString(res.getEntity(), "utf-8");
            return jsonStr;
        } catch (Exception e) {
            logger.error("获取用户信息失败：", e);
//			e.printStackTrace();
        }
        finally {
            if(httpclient != null)
                httpclient.close();
        }
        return null;
    }

    /**
     * 拼装字符串（非线程安全）
     * @param ids
     * @return
     */
    private String formatStr(Object msg,Object... ids){
        StringBuilder idSql = new StringBuilder();
        idSql.append(msg);
        int i = 0;
        while(i<ids.length) {
            idSql.append(ids[i]);
            i++;
        }
        return idSql.toString();
    }
}